#include "task_queue.h"
#include <stdio.h>
#include <stdlib.h>

TaskNode *
create_task (int task_id)
{
  TaskNode *new_task = (TaskNode *)malloc (sizeof (TaskNode));
  if (!new_task)
    {
      perror ("Memory allocation failed");
      exit (EXIT_FAILURE);
    }
  new_task->task_id = task_id;
  new_task->next = NULL;
  return new_task;
}

TaskNode *
reverse_task_queue_by_group (TaskNode *head, int k)
{
  TaskNode *hair = create_task (0);

  /* 用于辅助暂存任务队列 */
  hair->task_id = 0;
  hair->next = head;

  /* 标记翻转前的任务节点 */
  TaskNode *pre = hair;

  while (head != NULL)
    {
      TaskNode *tail = pre;

      /* 寻找当前组的尾节点，如果剩余节点不足k个，直接返回 */
      for (int i = 0; i < k; ++i)
      {
        tail = tail->next;
        if (tail == NULL)
        {
          return hair->next;
        }
      }

      TaskNode *next = tail->next;    /* 保存下一组的起始节点 */
      TaskNode *prev = tail->next;    /* 反转时用于记录前一个节点 */
      TaskNode *p = head;             /* 当前处理的节点 */

      /* 反转当前组的节点，直到到达尾节点 */
      while (prev != tail)
      {
        TaskNode *temp = p->next;   /* 暂存下一个节点 */
        p->next = prev;             /* 反转链接方向 */
        prev = p;                   /* 移动prev指针 */
        p = temp;                   /* 移动p指针 */
      }

      pre->next = tail;              /* 将前一部分与反转后的部分连接 */
      head->next = next;             /* 将反转后的部分与剩余列表连接 */
      pre = head;                    /* 更新pre指针为当前组的头节点 */
      head = next;                   /* 移动到下一组 */
    }

    return hair->next;
  }

void
free_task_queue (TaskNode *head)
{
  TaskNode *current = head;
  TaskNode *temp;
  while (current != NULL)
    {
      temp = current;
      current = current->next;
      free (temp);
    }
}

void
print_task_queue (TaskNode *head)
{
  TaskNode *current = head;
  while (current != NULL)
    {
      printf ("%d ", current->task_id);
      current = current->next;
    }
  printf ("\n");
}
